using IQIGame.Onigao.Framework;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    // BattleEffect需要兼容editor模式下的播放，所以不能改成controller管理的模式
    public class BattleEffectManager : Singleton<BattleEffectManager>
    {
        private BattleEffectManager()
        {
        }

        private bool enable { get; set; }
        private List<Effect> mEffects = new List<Effect>();
        private List<Effect> mEndEffect = new List<Effect>();
        private Dictionary<uint, Effect> mEffectDict = new Dictionary<uint, Effect>();

        public void Enable()
        {
            this.enable = true;
        }

        public void Disable()
        {
            this.enable = false;
        }

        public void Update(float deltaTime, float unScaledDeltaTime)
        {
            if (this.enable)
            {
                this.OnUpdate(deltaTime, unScaledDeltaTime);
            }
        }

        private void OnUpdate(float deltaTime, float unScaledDeltaTime)
        {
            for (int i = 0; i < this.mEffects.Count; i++)
            {
                this.mEffects[i]?.OnUpdate(deltaTime);
            }

            var nLen = this.mEndEffect.Count;
            for (int i = 0; i < nLen; i++)
            {
                int nIndex = nLen - 1 - i;
                var rEffect = this.mEndEffect[nIndex];
                if (rEffect.OnEndUpdate(deltaTime))
                {
                    this.Destroy(rEffect);
                }
            }
        }

        public Effect PlayEffect(EffectInitParam rParam, uint nGUID = 0)
        {
            var rEffect = this.CreateEffect(nGUID);
            rEffect.LoadAndPlay(rParam).Forget();
            return rEffect;
        }

        private Effect CreateEffect(uint nGUID = 0)
        {
            var rEffect = ClassPool.Get<Effect>();
            rEffect.Initialize(nGUID);
            this.mEffects.Add(rEffect);
            this.mEffectDict.Add(rEffect.GUID, rEffect);
            return rEffect;
        }

        public Effect GetEffect(uint nGUID)
        {
            this.mEffectDict.TryGetValue(nGUID, out var rEffect);
            return rEffect;
        }

        public void Stop(uint guid)
        {
            if (this.mEffectDict.TryGetValue(guid, out var rEffect))
            {
                this.Stop(rEffect);
            }
        }

        public void Stop(Effect effect)
        {
            if (this.mEffects.Remove(effect))
            {
                this.mEffectDict.Remove(effect.GUID);
                this.mEndEffect.Add(effect);
                effect.curPlayStage = EffectControlBehaviour.EEffectStageType.End;
            }
        }

        private void Destroy(Effect effect)
        {
            this.mEndEffect.Remove(effect);
            ClassPool.Put(effect);
        }

        public void StopAll()
        {
            for (int i = 0; i < this.mEffects.Count; i++)
            {
                var rEffect = this.mEffects[i];
                ClassPool.Put(rEffect);
            }
            for (int i = 0; i < this.mEndEffect.Count; i++)
            {
                var rEffect = this.mEndEffect[i];
                ClassPool.Put(rEffect);
            }
            this.mEffects.Clear();
            this.mEffectDict.Clear();
            this.mEndEffect.Clear();
        }
    }
}